#pragma once

#include <iostream>
#include <vector>
#include "Sem.hpp"
#include "mutex.hpp"

const int defaultcap=5;

using namespace std;
using namespace SemModule;
using namespace MutexModule;

template<class T>
class RingQueue
{
    public:
    RingQueue(int cap=defaultcap)
    :_cap(cap)
    ,_sem_blank(cap)
    ,_que(cap)
    ,_p_step(0)
    ,_c_step(0)
    ,_sem_data(0)
    {}
    void Equeue(const T &in)
    {
        _sem_blank.P();
        {
            LockGuard lg(_pmutex);
            _que[_p_step]=in;
            _p_step=(_p_step+1)%_cap;
        }
        _sem_data.V();
    }
    void Pop(T *out)
    {
        _sem_data.P();
        {
            LockGuard lg(_cmutex);
            *out=_que[_c_step];
            _c_step=(_c_step+1)%_cap;
        }
        _sem_blank.V();
    }
    private:

    vector<T> _que;
    int _cap;

    Sem _sem_blank;
    int _p_step;

    Sem _sem_data;
    int _c_step;

    Mutex _cmutex;
    Mutex _pmutex;
};